home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Codigo / hh / rsource.exe / Heretic Source / P_SIGHT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-13  |  6.4 KB  |  341 lines

  1. // P_sight.c
  2.  
  3. #include "DoomDef.h"
  4. #include "P_local.h"
  5.  
  6. /*
  7. ==============================================================================
  8.  
  9.                             P_CheckSight
  10.  
  11. This uses specialized forms of the maputils routines for optimized performance
  12.  
  13. ==============================================================================
  14. */
  15.  
  16. fixed_t        sightzstart;            // eye z of looker
  17. fixed_t        topslope, bottomslope;    // slopes to top and bottom of target
  18.  
  19. int            sightcounts[3];
  20.  
  21. /*
  22. ==============
  23. =
  24. = PTR_SightTraverse
  25. =
  26. ==============
  27. */
  28.  
  29. boolean        PTR_SightTraverse (intercept_t *in)
  30. {
  31.     line_t    *li;
  32.     fixed_t    slope;
  33.     
  34.     li = in->d.line;
  35.  
  36. //
  37. // crosses a two sided line
  38. //
  39.     P_LineOpening (li);
  40.  
  41.     if (openbottom >= opentop)    // quick test for totally closed doors
  42.         return false;    // stop
  43.  
  44.     if (li->frontsector->floorheight != li->backsector->floorheight)
  45.     {
  46.         slope = FixedDiv (openbottom - sightzstart , in->frac);
  47.         if (slope > bottomslope)
  48.             bottomslope = slope;
  49.     }
  50.     
  51.     if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
  52.     {
  53.         slope = FixedDiv (opentop - sightzstart , in->frac);
  54.         if (slope < topslope)
  55.             topslope = slope;
  56.     }
  57.     
  58.     if (topslope <= bottomslope)
  59.         return false;    // stop
  60.             
  61.     return true;    // keep going
  62. }
  63.  
  64.  
  65.  
  66. /*
  67. ==================
  68. =
  69. = P_SightBlockLinesIterator
  70. =
  71. ===================
  72. */
  73.  
  74. boolean P_SightBlockLinesIterator (int x, int y )
  75. {
  76.     int            offset;
  77.     short        *list;
  78.     line_t        *ld;
  79.     int            s1, s2;
  80.     divline_t    dl;
  81.     
  82.     offset = y*bmapwidth+x;
  83.     
  84.     offset = *(blockmap+offset);
  85.  
  86.     for ( list = blockmaplump+offset ; *list != -1 ; list++)
  87.     {
  88.         ld = &lines[*list];
  89.         if (ld->validcount == validcount)
  90.             continue;        // line has already been checked
  91.         ld->validcount = validcount;
  92.         
  93.         s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
  94.         s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
  95.         if (s1 == s2)
  96.             continue;        // line isn't crossed
  97.         P_MakeDivline (ld, &dl);
  98.         s1 = P_PointOnDivlineSide (trace.x, trace.y, &dl);
  99.         s2 = P_PointOnDivlineSide (trace.x+trace.dx, trace.y+trace.dy, &dl);
  100.         if (s1 == s2)
  101.             continue;        // line isn't crossed
  102.     
  103.     // try to early out the check
  104.         if (!ld->backsector)
  105.             return false;    // stop checking
  106.  
  107.     // store the line for later intersection testing
  108.         intercept_p->d.line = ld;
  109.         intercept_p++;
  110.     
  111.     }
  112.     
  113.     return true;        // everything was checked
  114. }
  115.  
  116. /*
  117. ====================
  118. =
  119. = P_SightTraverseIntercepts
  120. =
  121. = Returns true if the traverser function returns true for all lines
  122. ====================
  123. */
  124.  
  125. boolean P_SightTraverseIntercepts ( void )
  126. {
  127.     int                count;
  128.     fixed_t            dist;
  129.     intercept_t        *scan, *in;
  130.     divline_t    dl;
  131.     
  132.     count = intercept_p - intercepts;
  133. //
  134. // calculate intercept distance
  135. //
  136.     for (scan = intercepts ; scan<intercept_p ; scan++)
  137.     {
  138.         P_MakeDivline (scan->d.line, &dl);
  139.         scan->frac = P_InterceptVector (&trace, &dl);        
  140.     }
  141.     
  142. //
  143. // go through in order
  144. //    
  145.     in = 0;            // shut up compiler warning
  146.     
  147.     while (count--)
  148.     {
  149.         dist = MAXINT;
  150.         for (scan = intercepts ; scan<intercept_p ; scan++)
  151.             if (scan->frac < dist)
  152.             {
  153.                 dist = scan->frac;
  154.                 in = scan;
  155.             }
  156.             
  157.         if ( !PTR_SightTraverse (in) )
  158.             return false;            // don't bother going farther
  159.         in->frac = MAXINT;
  160.     }
  161.     
  162.     return true;        // everything was traversed
  163. }
  164.  
  165.  
  166.  
  167. /*
  168. ==================
  169. =
  170. = P_SightPathTraverse
  171. =
  172. = Traces a line from x1,y1 to x2,y2, calling the traverser function for each
  173. = Returns true if the traverser function returns true for all lines
  174. ==================
  175. */
  176.  
  177. boolean P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
  178. {
  179.     fixed_t    xt1,yt1,xt2,yt2;
  180.     fixed_t    xstep,ystep;
  181.     fixed_t    partial;
  182.     fixed_t    xintercept, yintercept;
  183.     int        mapx, mapy, mapxstep, mapystep;
  184.     int        count;
  185.         
  186.     validcount++;
  187.     intercept_p = intercepts;
  188.     
  189.     if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
  190.         x1 += FRACUNIT;                // don't side exactly on a line
  191.     if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
  192.         y1 += FRACUNIT;                // don't side exactly on a line
  193.     trace.x = x1;
  194.     trace.y = y1;
  195.     trace.dx = x2 - x1;
  196.     trace.dy = y2 - y1;
  197.  
  198.     x1 -= bmaporgx;
  199.     y1 -= bmaporgy;
  200.     xt1 = x1>>MAPBLOCKSHIFT;
  201.     yt1 = y1>>MAPBLOCKSHIFT;
  202.  
  203.     x2 -= bmaporgx;
  204.     y2 -= bmaporgy;
  205.     xt2 = x2>>MAPBLOCKSHIFT;
  206.     yt2 = y2>>MAPBLOCKSHIFT;
  207.  
  208. // points should never be out of bounds, but check once instead of
  209. // each block
  210.     if (xt1<0 || yt1<0 || xt1>=bmapwidth || yt1>=bmapheight
  211.     ||  xt2<0 || yt2<0 || xt2>=bmapwidth || yt2>=bmapheight)
  212.         return false;
  213.  
  214.     if (xt2 > xt1)
  215.     {
  216.         mapxstep = 1;
  217.         partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
  218.         ystep = FixedDiv (y2-y1,abs(x2-x1));
  219.     }
  220.     else if (xt2 < xt1)
  221.     {
  222.         mapxstep = -1;
  223.         partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
  224.         ystep = FixedDiv (y2-y1,abs(x2-x1));
  225.     }
  226.     else
  227.     {
  228.         mapxstep = 0;
  229.         partial = FRACUNIT;
  230.         ystep = 256*FRACUNIT;
  231.     }    
  232.     yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep);
  233.  
  234.     
  235.     if (yt2 > yt1)
  236.     {
  237.         mapystep = 1;
  238.         partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
  239.         xstep = FixedDiv (x2-x1,abs(y2-y1));
  240.     }
  241.     else if (yt2 < yt1)
  242.     {
  243.         mapystep = -1;
  244.         partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
  245.         xstep = FixedDiv (x2-x1,abs(y2-y1));
  246.     }
  247.     else
  248.     {
  249.         mapystep = 0;
  250.         partial = FRACUNIT;
  251.         xstep = 256*FRACUNIT;
  252.     }    
  253.     xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
  254.  
  255.     
  256. //
  257. // step through map blocks
  258. // Count is present to prevent a round off error from skipping the break
  259.     mapx = xt1;
  260.     mapy = yt1;
  261.  
  262.     
  263.     for (count = 0 ; count < 64 ; count++)
  264.     {
  265.         if (!P_SightBlockLinesIterator (mapx, mapy))
  266.         {
  267. sightcounts[1]++;
  268.             return false;    // early out
  269.         }
  270.         
  271.         if (mapx == xt2 && mapy == yt2)
  272.             break;
  273.             
  274.         if ( (yintercept >> FRACBITS) == mapy)
  275.         {
  276.             yintercept += ystep;
  277.             mapx += mapxstep;
  278.         }
  279.         else if ( (xintercept >> FRACBITS) == mapx)
  280.         {
  281.             xintercept += xstep;
  282.             mapy += mapystep;
  283.         }
  284.         
  285.     }
  286.  
  287.  
  288. //
  289. // couldn't early out, so go through the sorted list
  290. //
  291. sightcounts[2]++;
  292.  
  293.     return P_SightTraverseIntercepts ( );
  294. }
  295.  
  296.  
  297.  
  298. /*
  299. =====================
  300. =
  301. = P_CheckSight
  302. =
  303. = Returns true if a straight line between t1 and t2 is unobstructed
  304. = look from eyes of t1 to any part of t2
  305. =
  306. =====================
  307. */
  308.  
  309. boolean P_CheckSight (mobj_t *t1, mobj_t *t2)
  310. {
  311.     int        s1, s2;
  312.     int        pnum, bytenum, bitnum;
  313.  
  314. //
  315. // check for trivial rejection
  316. //
  317.     s1 = (t1->subsector->sector - sectors);
  318.     s2 = (t2->subsector->sector - sectors);
  319.     pnum = s1*numsectors + s2;
  320.     bytenum = pnum>>3;
  321.     bitnum = 1 << (pnum&7);
  322.     
  323.     if (rejectmatrix[bytenum]&bitnum)
  324.     {
  325. sightcounts[0]++;
  326.         return false;        // can't possibly be connected
  327.     }
  328.  
  329. //
  330. // check precisely
  331. //        
  332.     sightzstart = t1->z + t1->height - (t1->height>>2);
  333.     topslope = (t2->z+t2->height) - sightzstart;
  334.     bottomslope = (t2->z) - sightzstart;
  335.  
  336.     return P_SightPathTraverse ( t1->x, t1->y, t2->x, t2->y );
  337. }
  338.  
  339.  
  340.  
  341.